﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Linq;
using System.Data.Linq.Mapping;

namespace PDO.DataPersistence.Core
{
    public class PersistableDataObjectClassInfo
    {
        private Type _classType;
        private ObservableCollection<PropertyInfo> _queryablePropertyList;
        private ObservableCollection<PropertyInfo> _propertyInfoList;

        public PersistableDataObjectClassInfo(Type type)
        {
            ClassType = type;
        }


        public Type ClassType
        {
            get { return _classType; }
            set
            {
                _classType = value;
                QueryablePropertyInfoList = null; // clear to force reload
            }
        }


        private static bool IsQueryable(PropertyInfo pi)
        {
            bool ret = false;

            // Check for presence of ColumnAttribute attribute.
            if (pi.GetCustomAttributes(typeof(ColumnAttribute), false).Length > 0)
            {
                ret = true;
            }
            return ret;
        }



        public ObservableCollection<PropertyInfo> QueryablePropertyInfoList
        {
            get
            {
                if (null == _queryablePropertyList)
                {
                    _queryablePropertyList = new ObservableCollection<PropertyInfo>();
                    IEnumerable<PropertyInfo> info = ClassType.GetProperties().OrderBy(cmp => cmp, new PropertyInfoComparer());

                    
                    foreach (PropertyInfo pi in info)
                    {
                        if (IsQueryable(pi))
                        {
                            _queryablePropertyList.Add(pi);
                        }
                    }
                }
                return _queryablePropertyList;
            }
            private set { _queryablePropertyList = value; }
        }

        public IEnumerable<string> QueryablePropertyNameList
        {
            get
            {
                return ClassType.GetProperties().OrderBy(cmp => cmp, new PropertyInfoComparer()).Select(p2 => p2.Name);
            }
        }

        public ObservableCollection<PropertyInfo> BrowsablePropertyList
        {
            get
            {
                if (null == _propertyInfoList)
                {
                    _propertyInfoList = new ObservableCollection<PropertyInfo>();
                    IEnumerable<PropertyInfo> info = ClassType.GetProperties().OrderBy(cmp => cmp, new PropertyInfoComparer());
                    foreach (PropertyInfo pi in info)
                    {
                        if (ReflectionHelper.IsXmlSerializable(pi) && // only disply properties not marked with XmlIgnore
                            !pi.PropertyType.IsGenericType && // exclude PersistableDataObjectList<>'s
                            !pi.PropertyType.IsSubclassOf(typeof(PersistableDataObject))) // exclude child PersistableDataObjects
                        {
                            _propertyInfoList.Add(pi);
                        }
                    }
                }
                return _propertyInfoList;
            }
            private set { _propertyInfoList = value; }
        }


        public string SourceTableName
        {
            get { return PDOMapper.GetSourceDatabaseTableName(ClassType); }
        }

    }


    /// <summary>
    /// Comparer helper class
    /// </summary>
    public class PropertyInfoComparer : IComparer<PropertyInfo>
    {
        public int Compare(PropertyInfo d1, PropertyInfo d2)
        {
            return string.Compare(d1.Name, d2.Name, StringComparison.Ordinal);
        }
    }

}
